package com.zxj.camerapreview;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.locks.ReentrantLock;

import cn.iotnova.opus.utils.OpusRecorderTask;
import cn.iotnova.rtc.Rtcclient;

//https://blog.csdn.net/byhook/article/details/84037338
//width:1080,height:2019
//YUV420SP(NV21)
//YUV420P(YV12)

public class CameraSurfaceViewShowActivity extends AppCompatActivity implements SurfaceHolder.Callback, Camera.PreviewCallback {

    private static final String TAG = CameraSurfaceViewShowActivity.class.getName();
    private SurfaceView mSurfaceView;
    private SurfaceHolder mHolder;
    private Camera mCamera;
    private Camera.Parameters mParameters;
    private int camera_status = 0;

    Rtcclient rtcclient = new Rtcclient();

    Button btn_record;


    private String APP_PATH;
    private String APP_RECORDER_FILE_PATH;
    OpusRecorderTask opusRecorderTask = null;
    private String recorderFilePath;
    private String recorderPcmFilePath;
    private String recorderDecodedPcmFilePath;
    private AudioManager audioManager;
    private int permissionRequestCode;

    int width = 640;
    int height = 480;
    //int width = 480;
    //int height = 640;
    //int width = 1080;
    //int height = 2019;
    private Toast toast;

    private final void toast(String msg) {
        if (toast != null) {
            toast.cancel();
            toast = null;
        }

        toast = Toast.makeText((Context)this, (CharSequence)msg, Toast.LENGTH_LONG);
        toast.show();
    }

    @SuppressLint("NewApi")
    private final void startRecorder() {
        if (checkSelfPermission("android.permission.RECORD_AUDIO") == PackageManager.PERMISSION_DENIED) {
            //toast(getString(R.string.record_permission_denied));
            requestPermissions(new String[]{"android.permission.RECORD_AUDIO", "android.permission.READ_EXTERNAL_STORAGE", "android.permission.WRITE_EXTERNAL_STORAGE"}, this.permissionRequestCode);
        } else if (opusRecorderTask != null) {
            //toast(getString(R.string.play_error));
        } else {
            btn_record.setText("停止录制");
            //playPcmBtn.setEnabled(false);
            //playBtn.setEnabled(false);
            //opusRecorderTask = new OpusRecorderTask(recorderFilePath, recorderPcmFilePath);
            //(new Thread(opusRecorderTask)).start();
        }
    }

    @SuppressLint("NewApi")
    private final void stopRecorder() {
        //recorderBtn.setText(getString(R.string.start_record));
        btn_record.setText("开始录制");
        //playPcmBtn.setEnabled(true);
        //playBtn.setEnabled(true);
        if (opusRecorderTask != null) {
            opusRecorderTask.stop();
            opusRecorderTask = null;
        }

    }

    //https://blog.csdn.net/weixin_43889841/article/details/101750935
    @SuppressLint("NewApi")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_surface_view_show);
        mSurfaceView = (SurfaceView)findViewById(R.id.surfaceView);
        mHolder = mSurfaceView.getHolder();
        mHolder.addCallback(this);
        mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

/*
        new Thread(new Runnable() {
            @Override
            public void run() {
                rtcclient.ConnectToServer(1,0,"192.168.1.2");
            }
        }).start();
 */

        btn_record = findViewById(R.id.btn_record);

        btn_record.setOnClickListener(new View.OnClickListener() {

            @Override
            public void onClick(View v) {

                if (opusRecorderTask == null) {
                    startRecorder();
                } else {
                    stopRecorder();
                }
            }
        });



        audioManager = getSystemService(AudioManager.class);


        //TAG = getClass().getSimpleName();
        //APP_PATH = Environment.getExternalStorageDirectory().toString() + File.separator + "opusaudiodemo" + File.separator;
        APP_PATH = getFilesDir().toString() + File.separator + "opusaudiodemo" + File.separator;
        APP_RECORDER_FILE_PATH = APP_PATH + "recorder_file" + File.separator;

        recorderFilePath = APP_RECORDER_FILE_PATH + "recorder.ops";
        recorderPcmFilePath = APP_RECORDER_FILE_PATH + "recorder.pcm";
        recorderDecodedPcmFilePath = APP_RECORDER_FILE_PATH + "recorderDecoded.pcm";
        permissionRequestCode = 10;
        //AudioRecordManager.getInstance().startRecord("");

        //opusRecorderTask = new OpusRecorderTask(recorderFilePath, recorderPcmFilePath);
        //(new Thread(opusRecorderTask)).start();

        //startRecorder();

    }

    public void onChangeClick(View view) {
//        PropertyValuesHolder valuesHolder2 = PropertyValuesHolder.ofFloat("rotationX", 0.0f, 360.0f, 0.0F);
        PropertyValuesHolder valuesHolder = PropertyValuesHolder.ofFloat("rotationY", 0.0f, 360.0f, 0.0F);
        PropertyValuesHolder valuesHolder1 = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.5f,1.0f);
        PropertyValuesHolder valuesHolder3 = PropertyValuesHolder.ofFloat("scaleY", 1.0f, 0.5f,1.0f);
        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mSurfaceView,  valuesHolder,valuesHolder1,valuesHolder3);
        objectAnimator.setDuration(5000).start();
    }

    public void onSwitchClick(View view) {
        camera_status ^= 1;
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
        }
        mCamera = Camera.open(camera_status);
        try {
            mCamera.setDisplayOrientation(90);
            mCamera.setPreviewDisplay(mSurfaceView.getHolder());
        } catch (IOException e) {
            e.printStackTrace();
        }
        mCamera.startPreview();
    }

    //https://blog.csdn.net/qq_16775897/article/details/101620194
    byte[] frameBuffer;
    @Override
    public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
        Log.e(TAG,"surfaceCreated");
        try {
            frameBuffer = new byte[((width * height) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8];

            // Open the Camera in preview mode
            mCamera = Camera.open(camera_status);
            Camera.Parameters param = mCamera.getParameters();

            //https://www.jianshu.com/p/f07a42e1dd0a
            List<Camera.Size> listSize = param.getSupportedPreviewSizes();
            for (Camera.Size size : listSize) {
                System.out.println(size.width + "--------------------" + size.height);
            }


            param.setPictureFormat(PixelFormat.JPEG); //Sets the image format for picture 设定相片格式为JPEG，默认为NV21
            //param.setPreviewFormat(ImageFormat.NV21); //Sets the image format for preview picture，默认为NV21
            param.setPreviewFormat(ImageFormat.NV21); //Sets the image format for preview picture，默认为NV21
            //param.setPictureFormat(PixelFormat.RGBA_8888);
            //param.setPictureFormat(PixelFormat.RGB_565);
            //param.setPictureFormat(PixelFormat.YCbCr_420_SP);
            //param.setPreviewSize(width, height);

            param.setPreviewSize(width, height);

            param.setFlashMode(Camera.Parameters.FOCUS_MODE_AUTO);
            if (!Build.MODEL.equals("KORIDY H30")) {
                param.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);// 1连续对焦
            } else {
                param.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);
            }


            //<-处理变形
            int displayRotation = 0;
            WindowManager windowManager = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
            int rotation = windowManager.getDefaultDisplay().getRotation();
            switch (rotation) {
                case Surface.ROTATION_0:
                    displayRotation = 0;
                    break;
                case Surface.ROTATION_90:
                    displayRotation = 90;
                    break;
                case Surface.ROTATION_180:
                    displayRotation = 180;
                    break;
                case Surface.ROTATION_270:
                    displayRotation = 270;
                    break;
            }
            Camera.CameraInfo info = new Camera.CameraInfo();
            Camera.getCameraInfo(0, info);
            int orientation;
            if (info.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                orientation = (info.orientation - displayRotation + 360) % 360;
            } else {
                orientation = (info.orientation + displayRotation) % 360;
                orientation = (360 - orientation) % 360;
            }

            System.out.println("ImageFormat.getBitsPerPixel(ImageFormat.NV21)): " + ImageFormat.getBitsPerPixel(ImageFormat.NV21));

            //mCamera.addCallbackBuffer(new byte[((640 * 480) * ImageFormat.getBitsPerPixel(ImageFormat.NV21)) / 8]);
            //mCamera.addCallbackBuffer(new byte[((640 * 480) * ImageFormat.getBitsPerPixel(ImageFormat.RGB_565)) / 8]);
            //mCamera.addCallbackBuffer(frameBuffer); //Sets the image format for preview picture，默认为NV21
            //cameral.setPreviewCallbackWithBuffer()方法必须设置addCallbackBuffer(buffers)后onPreviewFrame()方法才会被持续调用

            //mCamera.setPreviewCallbackWithBuffer(this);

            mCamera.setPreviewCallback(this);

            mCamera.setParameters(param);
            mCamera.setDisplayOrientation(orientation);
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();

            //SendThread();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int format, int width, int height) {
        Log.e(TAG,"surfaceChanged format:"+format+",width:"+width+",height:"+height);
        /*mCamera.autoFocus(new Camera.AutoFocusCallback() {
            @Override
            public void onAutoFocus(boolean success, Camera camera) {
                Log.e(TAG,"onAutoFocus success:"+success);
                if (success) {
                    mParameters = mCamera.getParameters();
                    mParameters.setPictureFormat(PixelFormat.JPEG); //图片输出格式
//                    mParameters.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);//预览持续发光
                    mParameters.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_PICTURE);//持续对焦模式
                    mCamera.setParameters(mParameters);
                    mCamera.startPreview();
                    mCamera.cancelAutoFocus();
                }
            }
        });*/
    }

    @Override
    public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {
        Log.e(TAG,"surfaceDestroyed");
        if (mCamera != null) {
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    volatile boolean isDestroy = true;

    private ReentrantLock imageArrayLock = new ReentrantLock();
    @Override
    public void onPreviewFrame(byte[] bytes, Camera camera) {
        if (bytes == null) System.out.println("onPreviewFrame byte null");
        imageArrayLock.lock();

//        try {
//            Thread.sleep(60);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }

        //System.out.println(bytes.length);


            //final YuvImage image = new YuvImage(bytes, ImageFormat.NV21, width, height,null);
            //VideoServer.SendNV21Image(image.getYuvData(), image.getWidth(), image.getHeight());

            /*
            ByteArrayOutputStream os = new ByteArrayOutputStream(bytes.length);
            if (!image.compressToJpeg(new Rect(0, 0, width, height), 80, os)) {
                return ;
            }

            byte[] data = os.toByteArray();
            *
             */


            //bytesData = new byte[bytes.length];
            //System.arraycopy(bytes, 0, bytesData, 0, bytes.length);
            //frameComes = true;

        //bytesData = new byte[bytes.length];
        //System.arraycopy(bytes, 0, bytesData, 0, bytes.length);
        //VideoServer.SendNV21Image(bytesData, width, height, bytes.length);
        //VideoServer.SendNV21Image(bytes, width, height, bytes.length);
        rtcclient.SendNV21Image(bytes, width, height, bytes.length);

            //VideoServer.SendNV21Image(bytes_, width, height);

            //System.out.println("onPreviewFrame");

            //byte[] bytes_ = new byte[bytes.length];
            //yuv2rgba
            //YuvUtils.NV21ToI420(bytes, bytes_, width, height, false);

            //发现每次只调用一次，最后发现需要在onPreviewFrame()里面再调一次camera.addCallbackBuffer(new byte[bufferSize]);否则只调用一次！
            //VideoServer.SendNV21Image(bytes_, width, height);


            //byte[] bytes_ = NV21.yuv2rgba(bytes, width, height);
            //VideoServer.SendYUVImage(bytes_, width, height);

        imageArrayLock.unlock();
        //camera.
        //camera.addCallbackBuffer(frameBuffer);

    }



    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopRecorder();

        isDestroy = false;
    }
}